package icraf.carbon.gui.model;

import icraf.carbon.core.LandCoverList;
import icraf.carbon.core.Project;
import icraf.carbon.core.Zone;
import icraf.carbon.core.ZoneList;
import icraf.carbon.gui.MatrixTableModel;
import icraf.carbon.gui.NumberRowHeader;
import icraf.carbon.gui.MenuFactory.MenuProperty;
import icraf.carbon.model.ModelProject;

import java.awt.Color;
import java.util.HashSet;

import javax.swing.ListModel;

public class ModelSummaryZoneTableModel extends MatrixTableModel {
	private static final long serialVersionUID = 8968868974903218229L;
	private ModelProject modelProject;
	private boolean isCumulative = false;
	private boolean isEligibleOnly = false;
	private int valueType = Zone.NET_EMISSION;
	private boolean isTotalPerYear = false;
	private Color colorTotal = new Color(200, 180, 255);
	public static int DETAIL = 1, ZONE_SUMMARY = 0;
	private int listType = ZONE_SUMMARY;
	
	public ModelSummaryZoneTableModel() {
		super();
		setHighlightRowColor(colorTotal);
	}

	public boolean isCumulative() {
		return isCumulative;
	}

	public void setCumulative(boolean isCumulative) {
		this.isCumulative = isCumulative;
		fireTableDataChanged();
	}

	public ModelProject getModelProject() {
		return modelProject;
	}

	public void setModelProject(ModelProject modelProject) {
		this.modelProject = modelProject;
		fireTableStructureChanged();
		tableListModel.fireContentChange(getColumnCount());
		setListType(listType);
	}

	@Override
	public Class<?> getColumnClass(int column) {
//		if(getRowCount() == 0 || getValueAt(0, column) == null) return null;
//		return getValueAt(0, column).getClass();
		
		if(listType == ZONE_SUMMARY) {
			if (column == 0)
			return String.class;
			return Double.class;
		} else if(listType == DETAIL) {
			if (column <= 2)
				return String.class;
				return Double.class;
		}
		return getValueAt(0, column).getClass();
	}

	@Override
	public int getColumnCount() {
		if(modelProject == null) return 0;
		if(listType == ZONE_SUMMARY) {
			return modelProject.getIterationCount() + 2;
		} else if(listType == DETAIL) {
			return modelProject.getIterationCount() + 4;
		}
		return 0;
	}

	public String getColumnName(int col) {
		if(listType == ZONE_SUMMARY) {
			if (col == 0)
				return "Iteration Period ->";
			return Integer.toString((col - 1));
		} else if(listType == DETAIL) {
			switch (col) {
			case 0:
				return MenuProperty.PROJECT_ZONE.getLabel();
			case 1:
				return MenuProperty.PROJECT_LU_FROM.getLabel();
			case 2:
				return MenuProperty.PROJECT_LU_INTO.getLabel();
			}
			return Integer.toString((col - 3));
		}
		return "";
	}

	@Override
	public int getRowCount() {
		if(modelProject == null) return 0;
		if(listType == ZONE_SUMMARY) {
			return modelProject.getMainProject().getZoneList().getSize()+1;
		} else if(listType == DETAIL) {
			return getCombinationLC()*modelProject.getMainProject().getZoneList().getSize(); 
		}
		return 0;
	}
	
	private int getCombinationLC() {
		int n = modelProject.getMainProject().getLandCoverList().size();
		return n*n;
	}

	@Override
	public Object getValueAt(int row, int column) {
		if(listType == ZONE_SUMMARY) {
			if(row == getRowCount()-1) {
				if (column == 0) {
					return "TOTAL";
				}
				double tot = 0;
				for(int i = 0; i < getRowCount()-1; i++) {
					tot += (Double)getValueAt(i, column);
				}
				return tot;
			}
			
			if (column == 0) {
				return modelProject.getMainProject().getZoneList().get(row).getLabel();
			}
//			if(isPercentageOutput) {
//				Project p = modelProject.getSimulatedProject(column-1);
//				return 100*getEmissionByZone(column-1, row)/(p.getTotalEmission()+p.getTotalSequestration());
//			}
			double v = 0;
			if(isCumulative && column > 1) {
				v = (Double)getValueAt(row, column-1); 
			}
			return v+getEmissionByZone(column-1, row);
		} else if(listType == DETAIL) {
			LandCoverList ls = modelProject.getMainProject().getLandCoverList();
			ZoneList zs = modelProject.getMainProject().getZoneList();
			int zi = row/getCombinationLC();
			int li1 = (row%getCombinationLC())/ls.size();
			int li2 = row%ls.size();
			switch (column) {
			case 0:
				return zs.get(zi).getLabel();
			case 1:
				return ls.get(li1).getLabel();
			case 2:
				return ls.get(li2).getLabel();
			}
			Project p = modelProject.getSimulatedProject(column-3);
			if(isEligibleOnly && (!p.getZoneList().get(zi).isEligible() || !p.isEligible(p.getLandCoverList().get(li1), p.getLandCoverList().get(li2)))) {
				return null;
			}
			double e = p.getZoneList().get(zi).getEmission(p.getLandCoverList().get(li1), p.getLandCoverList().get(li2));
//			if(isPercentageOutput) {
//				return 100*e/(p.getTotalEmission()+p.getTotalSequestration());
//			}
			double v = 0;
			if(isCumulative && column > 3) {
				v = (Double)getValueAt(row, column-1);
			}
			if(isTotalPerYear) {
				return (e+v)*p.getTotalArea();
			}
			return e+v;
			
		}
		return null;
	}
	
	public double getEmissionByZone(int iteration, int zoneIdx) {
		Project p = modelProject.getSimulatedProject(iteration);
		Zone z = p.getZoneList().get(zoneIdx);
		//if(isTotalPerYear&& !isPercentageOutput) {
		if(isTotalPerYear) {
			return p.getTotalArea()*z.getEmissionTotal(valueType, isEligibleOnly);
		}
		return z.getEmissionTotal(valueType, isEligibleOnly);
	}
	

	public boolean isCellEditable(int row, int col) {
		return false;
	}

	private NumberRowHeader tableListModel = new NumberRowHeader(this);
	//private boolean isPercentageOutput = false;

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public ListModel getRowHeaderModel() {
		return tableListModel;
	}

	public boolean isEligibleOnly() {
		return isEligibleOnly;
	}

	public void setEligibleOnly(boolean isEligibleOnly) {
		this.isEligibleOnly = isEligibleOnly;
		fireTableDataChanged();
	}

	public int getValueType() {
		return valueType;
	}

	public void setValueType(int valueType) {
		this.valueType = valueType;
//		isPercentageOutput = false;
		fireTableDataChanged();
	}

	public boolean isTotalPerYear() {
		return isTotalPerYear;
	}

	public void setTotalPerYear(boolean isTotalPerYear) {
		this.isTotalPerYear = isTotalPerYear;
		fireTableDataChanged();
	}

	public void setListType(int listType) {
		this.listType = listType;
		fireTableStructureChanged();
		tableListModel.fireContentChange(this.getRowCount()-1);
		if(listType == DETAIL) {
			getHighlightRows().clear();
		} else if(listType == ZONE_SUMMARY) {
			HashSet<Integer> rs = getHighlightRows();
			rs.clear();
			rs.add(getRowCount()-1);
		}
	}

//	public void setPercentageOutput(boolean b) {
//		isPercentageOutput = b;
//		if(b) valueType = Zone.NET_EMISSION;
//		fireTableDataChanged();
//	}

//	public boolean isPercentageOutput() {
//		return isPercentageOutput;
//	}


}
